using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using SharedKernel.Infrastructure.Caches;
using SharedKernel.Infrastructure.Comm;
using SharedKernel.Infrastructure.Redis;
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using UserService.Application.DTOs;
using UserService.Application.Services;
using UserService.Controllers;
using UserService.Domain.Models;
using UserService.Domain.Repositories;
using UserService.Domain.ValueObjects;

namespace UserService.Application.Services
{
    /// <summary>
    /// 用户应用服务实现
    /// </summary>
    public class UserAppService : IUserAppService
    {
        private readonly IUserRepository _userRepository;
        private readonly IConfiguration _configuration;
        private readonly ICacheService _cacheService;
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="userRepository">用户仓储</param>
        public UserAppService(IUserRepository userRepository, IConfiguration configuration, ICacheService cacheService)
        {
            _userRepository = userRepository;
            _configuration=configuration;
            _cacheService=cacheService;
            _cacheService.ChangeDataBase(RedisDbConstConfig.UserServiceDb);
        }

        /// <summary>
        /// 获取用户
        /// </summary>
        /// <param name="id">用户ID</param>
        /// <returns>用户实体</returns>
        public async Task<User> GetUserAsync(long id)
        {
            return await _userRepository.SingleAsync(id);
        }

        /// <summary>
        /// 用户登录
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<ResponseInfo<UserLoginResInfo>> UserLogin(UserLoginRequest request)
        {
            var res = ResponseInfo<UserLoginResInfo>.Fail();
            var user = await _userRepository.GetUserLogin(new UserLoginValueObject
            {
                Password = request.Password,
                Phone = request.Phone,
            });
            if (user == null||user.Id<=0)
            {
                return res.SetFail("手机号或密码错误");
            }

            var resData = new UserLoginResInfo
            {
                Account=user.Account,
                Name=user.Name,
                Phone=user.Phone,
                Id = user.Id,
            };

            var minute = Convert.ToInt32(_configuration["Jwt:ExpirationMinute"]);
            var claims = new[]
            { 
                //JWT唯一ID
                new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
                new Claim(ClaimTypes.NameIdentifier, resData.Id.ToString()),
                new Claim(ClaimTypes.Name,  resData.Name),
                //权限点
                new Claim(ClaimTypes.Role, "User"),
            };

            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:Key"]));
            var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

            var token = new JwtSecurityToken(
                issuer: _configuration["Jwt:Issuer"],
                audience: _configuration["Jwt:Audience"],
                claims: claims,
                expires: DateTime.Now.AddMinutes(minute),
                signingCredentials: creds);

            resData.Token=new JwtSecurityTokenHandler().WriteToken(token);

            var userTokenKey = RedisKeyConstConfig.UserServiceLoginToken(resData.Id);
            //添加进缓存
            await _cacheService.SetAsync(userTokenKey, resData.Token, TimeSpan.FromMinutes(minute));

            return res.SetSuccess(data: resData);
        }

        /// <summary>
        /// 根据用户名获取用户
        /// </summary>
        /// <param name="username">用户名</param>
        /// <returns>用户实体</returns>
        public async Task<User> GetUserByUsernameAsync(string username)
        {
            return await _userRepository.GetByUsernameAsync(username);
        }

        /// <summary>
        /// 创建用户
        /// </summary>
        /// <param name="data">用户名</param> 
        /// <returns>创建的用户ID</returns>
        public async Task<long> CreateUserAsync(CreateUserRequest data)
        {
            var valueObj = new CreateUserValueObject
            {
                Name=data.Name
            };
            var user = User.Create(valueObj);
            await _userRepository.InsertAsync(user);
            return user.Id;
        }

        /// <summary>
        /// 更新用户信息
        /// </summary>
        /// <param name="data">用户ID</param> 
        public async Task UpdateUserAsync(long id, UpdateUserRequest data)
        {
            var valueObj = new UpdateUserValueObject
            {
                Name=data.Name
            };
            var user = await _userRepository.SingleAsync(id);
            if (user == null)
                throw new Exception("用户不存在");

            user.Update(valueObj);
            await _userRepository.UpdateAsync(user);
        }

        /// <summary>
        /// 更改密码
        /// </summary>
        /// <param name="id">用户ID</param>
        /// <param name="newPasswordHash">新密码哈希</param>
        public async Task ChangePasswordAsync(long id, string newPasswordHash)
        {
            var user = await _userRepository.SingleAsync(id);
            if (user == null)
                throw new Exception("用户不存在");

            user.ChangePassword(newPasswordHash);
            await _userRepository.UpdateAsync(user);
        }
    }
}